#include "funcoes.h"
#include "server.h"

SocketClient::~SocketClient(){
	dbConnection.disconnectFromDb();
}

SocketClient::SocketClient() {
	id = -1;
	sck = NULL;
	pthread_mutex_init(&Server::mutex,NULL);
}

void printFrame(QStringList frame) {
		while(frame.size() != 0) {
		printf("PRINTFUAME %s\n",frame.front().toStdString().c_str());
		frame.pop_front();
	}
	printf("\n\n");
}

int SocketClient::sendFunction(int idFunction,QStringList Parans) {
	if(!sck || sck->state() != QAbstractSocket::ConnectedState || id == -1)  {
		return 0;
		printf("PORRA KRAIO\n");
	}
	printFrame(Parans);
	pthread_mutex_lock(&Server::mutex);
	//printf("MANDA DO UM %i\n",idFunction);
	Parans.push_front(QString::number(id));
	Parans.push_front(QString::number(idFunction));
	QByteArray block;
	QDataStream out(&block, QIODevice::WriteOnly);
	out.setVersion(QDataStream::Qt_4_0);

	out << Parans;
	out.device()->seek(0);
	sck->write(block);
	sck->flush();
	pthread_mutex_unlock(&Server::mutex);
	return 1;
}

QStringList SocketClient::treatWellList() {
	pthread_mutex_lock(&Server::mutex);
	QStringList s = dbConnection.getWellList();
	pthread_mutex_unlock(&Server::mutex);
	sendFunction(GET_WELL_LIST,s);
	return s;
}

QStringList SocketClient::treatMastersList() {
	pthread_mutex_lock(&Server::mutex);
	QStringList s = dbConnection.getMastersList();
	pthread_mutex_unlock(&Server::mutex);
	sendFunction(GET_MASTERS_LIST,s);
	return s;
}


QStringList SocketClient::loginRequest(QStringList Param) {
	QString Par;
	QString login;
	QString senha;
	int id;	
	QStringList ParamToSend;
	
	
	Par = Param.front();
	Param.pop_front();
	id = Par.toInt();
	
	login = Param.front();
	Param.pop_front();
	
	senha = Param.front();
	Param.pop_front();
	if(!dbConnection.connectToDb("grupo01",login.toStdString().c_str(),senha.toStdString().c_str())) {
		ParamToSend.push_back(QString::number(0));
		this->sendFunction(HAND_SHAKE,ParamToSend);
		QTimer::singleShot(1000,sck,SLOT(deleteLater()));
	} else {
		ParamToSend.push_back(dbConnection.getUserLevel(login));
		this->sendFunction(HAND_SHAKE,ParamToSend);
	}
	return ParamToSend;
}

QStringList SocketClient::treatRegisterWell(QStringList Param) {
	QStringList ParamToSend;	
	QString Par = "insert into wells (idwell,nome,idsimulador) values(";
	
	Param.pop_front(); //ID Cliete
	
	if(Param.front() == "")
		goto out;
	Par += Param.front() + ",";
	Param.pop_front(); //Id
	if(Param.front() == "")
		goto out;	

	Par += "'" + Param.front() + "',";
	Param.pop_front(); //Nome
	if(Param.front() == "")
		goto out;	

	Par += Param.front() + ")";
	Param.pop_front(); //IdMaster
	printf("Executando a query : %s\n",	Par.toStdString().c_str());
	if(dbConnection.executeQuery(Par)) {
		ParamToSend.push_back(QString::number(1));
	} else {
		ParamToSend.push_back(QString::number(0));
	}
	this->sendFunction(REGISTER_WELL,ParamToSend);
	return ParamToSend;
	
	out:
	ParamToSend.push_back(QString::number(0));
	this->sendFunction(REGISTER_WELL,ParamToSend);
	return ParamToSend;
}



QStringList SocketClient::treatGetStateWell(QStringList Param) {
	QStringList ParamToSend;
	int status, idSimulador;	
	QString wellId;
	uint8_t data[20000];
	uint16_t dataLen, registerId;
	
	Param.pop_front(); //ID Cliete
	wellId = Param.front();//WellId
	Param.pop_front();
	
	idSimulador = Param.front().toInt();//Id Simulador 
	Param.pop_front();	
	
	registerId = Param.front().toInt();//RegisterId
	Param.pop_front();
	
	pthread_mutex_lock(&Server::mutex);
	int id = Server::wMap[wellId].id;
	pthread_mutex_unlock(&Server::mutex);	
	status = Server::sMap[idSimulador].M->requestReadAndWait(1500,data,id,registerId,dataLen,1);
	if(status == MODBUS_OK) {
		pthread_mutex_lock(&Server::mutex);
		ParamToSend.push_back(Server::wMap[wellId].name);
		pthread_mutex_unlock(&Server::mutex);
		ParamToSend.push_back(QString::number(data[0]));	
	} else {
		//printf("POCO DEU ERRO %i\n",status);
		ParamToSend.push_back(wellId);
		ParamToSend.push_back(QString::number(status));
	}
	this->sendFunction(GET_STATE_WELL,ParamToSend);	
	return ParamToSend;
}

QStringList SocketClient::trestGetAllDataFromWellAux(uint8_t wellId,int idSimulador,QStringList ParamToSend, uint16_t registerId, int numberOdRegisters) {
	uint8_t data[20000];
	int nBytes = (registerId > 20000);
	uint16_t dataLen;
	int status;	
	status = Server::sMap[idSimulador].M->requestReadAndWait(1000,data,wellId,registerId,dataLen,numberOdRegisters);
	if(status == MODBUS_OK) {
			ParamToSend.push_back(QString::number(data[0] + nBytes * 256 * data[1])); 
			//printf("DADO DO REGISTRADOR %i = %i\n",registerId,data[0] + nBytes * 256 * data[1]);
	} else {
		//printf("ERRO NA AQUISICAO DO REGISTRADOR %i %i\n",registerId, status);
		ParamToSend.push_back(QString::number(status));
	}
	return ParamToSend;
}

QStringList SocketClient::trestGetAllDataFromWell(int wellId, int idSimulador) {
	QStringList ParamToSend;
	QString time;
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,1,1); //ResetMa
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,100,1); //Global Off
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,101,1); //Start Motor Host
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,30302,1); //current production
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,30303,1);// yesterday production
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,30404,1);//current cycle count
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,30405,1);//yesterday cicle count
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,30406,1);//current porcetn run
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,30407,1);//yesterday porcent run
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,30408,1);//Cpm
	time = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,40100,1).back();//downtime hours
	time += ":" + trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,40101,1).back();//downtime minutes
	ParamToSend.push_back(time);
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,40102,1);//control mode
	return ParamToSend;
}

QStringList SocketClient::trestGetAllDataFromWell(QStringList Param) {	
	QStringList ParamToSend;
	QString wellId;
	int idSimulador;
	
	Param.pop_front(); //ID Cliete
	wellId = Param.front();//WellId
	Param.pop_front();
	
	idSimulador = Param.front().toInt();//Id Simulador 
	Param.pop_front();
	ParamToSend.push_back(wellId); //Id Do Poco cujo dados foi requisitado
	pthread_mutex_lock(&Server::mutex);
	ParamToSend += trestGetAllDataFromWell(Server::wMap[wellId].id,idSimulador);
	pthread_mutex_unlock(&Server::mutex);
	this->sendFunction(GET_ALL_DATA_FROM_WELL,ParamToSend);
	QStringList ParamToSend2 = ParamToSend;
	while(ParamToSend2.size() != 0) {
		printf("NO SERVIDOR O GET ALL DATA %s\n",ParamToSend2.front().toStdString().c_str());
		ParamToSend2.pop_front();
	}
	
	return ParamToSend;	
}

QStringList SocketClient::trestGetLetterFromWellAux(int wellId,int idSimulador) {
	pthread_mutex_lock(&Server::mutex);
	QStringList ParamToSend;
	printf("%s %s %i %i\n",__FILE__,__FUNCTION__,__LINE__,wellId);
	int status;
	uint16_t dataLen;
	printf("%s %s %i %i\n",__FILE__,__FUNCTION__,__LINE__,wellId);
	uint8_t data[20000];
	status = Server::sMap[idSimulador].M->requestReadAndWait(1500,data,wellId,32749,dataLen,207);
	if(status != MODBUS_OK){
		std::cout << "ERRO NA AQUISICAO DA CARTA\n";
		ParamToSend.push_back(QString::number(-1));
		printf("%s %s %i %i %i\n",__FILE__,__FUNCTION__,__LINE__,wellId,idSimulador);
		pthread_mutex_unlock(&Server::mutex);
		return ParamToSend; 	
	}
	printf("%s %s %i %i\n",__FILE__,__FUNCTION__,__LINE__,wellId);
	std::cout << "DADO DA CARTA NO SERVIDOR\n segundos = " << data[0] + 256 * data[1] + 512 * data[2] + 1024 * data[3] << std::endl <<
	"NUMERO DE PONTOS" << data[4]  + 256* data[5] << std::endl <<
	"Escala Maxima" << data[6] +  256* data[7] << std::endl <<
	"Escala Minima" << data[8] + 256* data[9] << std::endl <<
	"Stro Lenght" << data[10] + 256* data[11] << std::endl <<
	"Stro Period" << data[12] + data[13] << std::endl << "TUPLAS" << std::endl;
	for (int i=0; i<400; i++) {
		std::cout << (unsigned)data[i + 14] << " ";                                                                                                                 
	}
	std::cout << std::endl;
	ParamToSend.push_back(QString::number(data[0] + 256 * data[1] + 512 * data[2] + 1024 * data[3])); // segundos
	ParamToSend.push_back(QString::number(data[4] + 256 * data[5])); // N de pontos
	ParamToSend.push_back(QString::number(data[6] + 256 * data[7])); // Escala Maxima
	ParamToSend.push_back(QString::number(data[8] + 256 * data[9])); // Escala Minima
	ParamToSend.push_back(QString::number(data[10] + 256 * data[11])); // Stroke Lenght
	ParamToSend.push_back(QString::number(data[12] + 256 * data[13])); //  Stroke Period
	for (int i=0; i<400; i++) {
		ParamToSend.push_back(QString::number(data[i + 14]));                                                                                                                 
	}
	printf("%s %s %i %i\n",__FILE__,__FUNCTION__,__LINE__,wellId);
	pthread_mutex_unlock(&Server::mutex);
	return ParamToSend;
}

QStringList SocketClient::trestGetLetterFromWell(QStringList Param) {
	QStringList ParamToSend;
	QString wellId;
	int idSimulador;
	
	Param.pop_front(); //ID Cliete
	wellId = Param.front();//WellId
	Param.pop_front();
	
	idSimulador = Param.front().toInt();//Id Simulador
	Param.pop_front();
	
	ParamToSend.push_back(wellId);
	pthread_mutex_lock(&Server::mutex);
	int i = Server::wMap[wellId].id;
	pthread_mutex_unlock(&Server::mutex);	
	ParamToSend += trestGetLetterFromWellAux(i,idSimulador);

	std::cout << "ERRO NA AQUISICAO DA CARTA2" << wellId.toStdString() << "\n";

	this->sendFunction(GET_LETTER_FROM_WELL,ParamToSend);
	return ParamToSend;
}


QStringList SocketClient::treatDeleteWell(QStringList Param) {
	QStringList ParamToSend;
	QString query = "delete from wells where nome='";
	QString wellName;	
	
	Param.pop_front(); //ID Cliete
	wellName = Param.front();
	query += wellName + "'";
	
	////printf("Executando a query : %s\n",	query.toStdString().c_str());
	if(dbConnection.executeQuery(query)) {
		ParamToSend.push_back(QString::number(1));
	} else {
		ParamToSend.push_back(QString::number(0));
	}
	this->sendFunction(DELETE_WELL,ParamToSend);
	return ParamToSend;		
}

void SocketClient::processAux(QStringList frame) {
	QString Par = frame.front();
	int intPar = Par.toInt();
	frame.pop_front();
	printf("TO NO PROCESS 2 %i\n",intPar);
	switch(intPar) {
		case HAND_SHAKE:
			loginRequest(frame);
			break;
		case GET_WELL_LIST:
			treatWellList();
		break;
		case REGISTER_WELL:
			treatRegisterWell(frame);
		break;
		case GET_STATE_WELL:
			treatGetStateWell(frame);			
		break;
		case GET_ALL_DATA_FROM_WELL:
			trestGetAllDataFromWell(frame);
		break;
		case GET_MASTERS_LIST:
			treatMastersList();
		break;
		case GET_LETTER_FROM_WELL: 
			trestGetLetterFromWell(frame);
		break;
		case DELETE_WELL:
			treatDeleteWell(frame);
		break;
		case GET_ALARMS_FROM_WELL:
			treatGetAlarmsFromWell(frame);
		break;
		case GET_HISTORIC_FROM_WELL:
			printf("NO GET HISTOR\n");
			treatGetHistoricFromWell(frame);
		break;
		case CHANGE_TIMEOUT_WELL:
			treaChangeTimeout(frame);
		break;
		default:
		break;		
	}
}

void SocketClient::process(){
		pthread_mutex_lock(&Server::mutex);
		QStringList tmp = requestsVector.back();
		requestsVector.pop_back();
		pthread_mutex_unlock(&Server::mutex);
		processAux(tmp);
}

void SocketClient::addRequest(QStringList re) {
	printf("ADICIONANDO REQUEST A FILA\n");
	pthread_mutex_lock(&Server::mutex);
	requestsVector.push_front(re);
	pthread_mutex_unlock(&Server::mutex);
	MyThread *t = new MyThread();
	tVector.push_back(t);
	t->thz = this;
	t->start();
}

QString SocketClient::alarmToDB(int wellId, int idSimulador) {
	wells tmp;
	QStringList ParamToSend = treatGetAlarmsFromWellAux(wellId,idSimulador);
	for(int i = 0; i < 5; i++) {
		tmp.alarms[i] = ParamToSend.front().toInt(); ParamToSend.pop_front();//wellId
	}	
	return tmp.getStringAlarms();
}

QStringList SocketClient::treatGetAlarmsFromWellAux(int wellId, int idSimulador) {
	QStringList ParamToSend;
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,10001,1); //Falha no sensor de posicao
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,10002,1); //derrapagem de correia
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,10003,1); //lim max de freq de motor
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,10004,1); //lim min de freque de motor
	ParamToSend = trestGetAllDataFromWellAux(wellId,idSimulador,ParamToSend,10005,1); //falha sensor carga*/
	return ParamToSend;
}

QStringList SocketClient::treatGetAlarmsFromWell(QStringList Param) {
	QStringList ParamToSend;
	QString wellId;
	int idSimulador;
	
	Param.pop_front(); //ID Cliete
	wellId = Param.front();//WellId
	Param.pop_front();
	
	idSimulador = Param.front().toInt();//Id Simulador
	Param.pop_front();
	ParamToSend.push_back(wellId);
	printf("TRATANDO ALARMES %s\n",wellId.toStdString().c_str());
	pthread_mutex_unlock(&Server::mutex);
	int i = Server::wMap[wellId].id;
	pthread_mutex_unlock(&Server::mutex);
	ParamToSend += treatGetAlarmsFromWellAux(i,idSimulador);
	this->sendFunction(GET_ALARMS_FROM_WELL,ParamToSend);
	return ParamToSend;		
}

QStringList SocketClient::treatGetHistoricFromWell(QStringList Param) {
	QStringList ParamToSend;	
	QString wellId;
	
	Param.pop_front(); //ID Cliete
	wellId = Param.front();//WellId
	Param.pop_front();
	
	ParamToSend.push_back(wellId);
	pthread_mutex_lock(&Server::mutex);
	ParamToSend += dbConnection.getHistoricFromWell(Server::wMap[wellId].id,Server::wMap[wellId].idSimulador);
	pthread_mutex_unlock(&Server::mutex);
	this->sendFunction(GET_HISTORIC_FROM_WELL,ParamToSend);
	return ParamToSend;
}

QStringList SocketClient::treaChangeTimeout(QStringList Param) {
	pthread_mutex_lock(&Server::mutex);
	QStringList ParamToSend;	
	QString wellId;
	int newValue;
	char query[200];
	
	Param.pop_front(); //ID Cliete
	wellId = Param.front();//WellId
	Param.pop_front();

	newValue = Param.front().toInt();//newValue
	Param.pop_front();
	
	Server::wMap[wellId].timeDefaut = newValue;
	//if(newValue > Server::wMap[wellId].timeLeft)
	//	Server::wMap[wellId].timeLeft = newValue;
	
	sprintf(query,"update wells set inte=%i where nome='%s'",newValue,wellId.toStdString().c_str());
	
	ParamToSend.push_back(wellId);
	ParamToSend.push_back(QString::number(dbConnection.executeQuery(query)));
	pthread_mutex_unlock(&Server::mutex);
	this->sendFunction(CHANGE_TIMEOUT_WELL,ParamToSend);
	return ParamToSend;
}
